import webapp2
import cgi
import urllib
import random
from google.appengine.ext import ndb
from google.appengine.api import users
import sha



PRIVILEGED_USERS = ['ceff939c77f0d527d744c20bd416c131f5cb8016',
                    'd2df7c9e7247432cbf5b4cb02ed030035507f396']

def isPrivileged(userName):
    return (sha.sha(userName).hexdigest() in PRIVILEGED_USERS)

class LayerFile(ndb.Model):
    content = ndb.StringProperty(indexed=False)
    date = ndb.DateTimeProperty(auto_now_add=True)

class ConfigFile(ndb.Model):
    content = ndb.StringProperty(indexed=False)
    date = ndb.DateTimeProperty(auto_now_add=True)

class MainPage(webapp2.RequestHandler):
    def get(self):

        wantOut = cgi.escape(self.request.get('logout'))
        if not self.isDegenerate({wantOut}):
            if wantOut == "true":
                if users.get_current_user():
                    self.redirect(users.create_logout_url(self.request.uri))
                else:
                    self.response.write("Not logged in")
                return
            
        if len(self.request.arguments()) == 0:
            if users.get_current_user():
                self.redirect("editor/editor-110914.html")
            else:
                self.redirect(users.create_login_url(self.request.uri))
            return

##        if len(self.request.arguments()) == 0:
##            self.redirect("editor/editor-180714.html")
##            return
##
##        wantIn = cgi.escape(self.request.get('login'))
##        if not self.isDegenerate({wantIn}):
##            if wantIn == "true":
##                if users.get_current_user():
##                    self.response.write("Already logged in")
##                else:
##                    self.redirect(users.create_login_url(self.request.uri))
##                return
        
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        
        if (self.isInitRequest()):
            self.response.write("Initialization complete.")
            return

        wantRemove = cgi.escape(self.request.get('remove'))
        if not self.isDegenerate({wantRemove}):
            user = users.get_current_user()
            if not user:
                self.error(401)
                return

            if not isPrivileged(user.nickname()):
                self.error(401)
                return

            if (self.removeLayerFromConfig(wantRemove)):
                self.response.write("Remove successfull")
            else:
                self.response.write("Remove failed")
            return
        
        layerName = cgi.escape(self.request.get('name'))
        if layerName in ["", None]:
            self.response.write("Usage:\r\n/?name=[layer_name || config]")
            return
        if layerName == "config":
            conf = self.getConfig()
            if conf == None:
                self.response.write("Sorry, no config file.")
            else:
                self.response.write(conf)
        else:
            layer = self.getLayer(layerName)
            if layer == None:
                self.response.write("Sorry, layer not found.")
            else:
                self.response.write(layer)

    def isInitRequest(self):
        booly = cgi.escape(self.request.get("initplx"))
        if booly in ["", None]:
            return False
        self.doInit()
        return True

    def doInit(self):
        layer = LayerFile(parent=ndb.Key('LayerFile', 'dummy'))
        layer.content = 'dummy'
        layer.put()
        config = ConfigFile(parent=ndb.Key('ConfigFile', 'dummy'))
        config.content = ""
        config.put()
                        
    def post(self):
        
        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        
        wantOut = cgi.escape(self.request.get('logout'))
        if not self.isDegenerate({wantOut}):
            if wantOut == "true":
                if users.get_current_user():
                    self.redirect(users.create_logout_url(self.request.uri))
                else:
                    self.response.write("Not logged in")
                return
         
        user = users.get_current_user()
        if not user:
            self.error(401)
            return

        if not isPrivileged(user.nickname()):
            self.error(401)
            return

        remove = cgi.escape(self.request.get('remove'))
        if not self.isDegenerate({remove}):
            if (self.removeLayerFromConfig(remove)):
                self.response.write("Remove successfull")
            else:
                self.response.write("Remove failed")
            return
            
        
        layerName = cgi.escape(self.request.get('name'))
        layerVersion = cgi.escape(self.request.get('version'))
        content = self.request.body
        if self.isDegenerate({layerName, layerVersion, content}):
            self.response.write("Usage:\r\n/?name=[layer_name]&version=[version]...content")
            return
        self.setLayer(layerName, content)
        self.addLayerToConfig(layerName, layerVersion)

    def removeLayerFromConfig(self, layerName):
        dic = self.getLayersDic()
        if layerName in dic:
            dic.pop(layerName)
            self.setConfig(dic)
            return True
        return False 
    
    def isDegenerate(self, someSet):
        return len({"",None}.intersection(someSet))!=0

    def setLayer(self, layerName, content):
        layer = LayerFile(parent=ndb.Key('LayerFile', layerName))
        layer.content = content
        layer.put()

    def dicToString(self, dic):
	return " ".join([k+":"+dic[k] for k in dic])

    def setConfig(self, dic):
        dicString = self.dicToString(dic)
        config = ConfigFile(parent=ndb.Key('ConfigFile', 'config'))
        config.content = dicString
        config.put()

    def getLayersDic(self):
        res = ""
        try:
            res = self.getConfig()
        except:
            res = None
        if res in ["",None]:
            return dict()
        return self.stringToDic(res)
        
    def stringToDic(self, string):
	b = string.split(" ")
	d = dict()
	for k in b:
		k = k.split(":")
		d[k[0]] = k[1]
	return d    

    def addLayerToConfig(self, layerName, layerVersion):
        dic = self.getLayersDic()
        dic[layerName] = layerVersion
        self.setConfig(dic)
        
    def getLayer(self, layerName):
        layersQuery = LayerFile.query(
                ancestor=ndb.Key('LayerFile', layerName)).order(-LayerFile.date)
        layers = layersQuery.fetch(1)
        if len(layers) == 0:
            return None
        for layer in layers:
            return layer.content
        
    def getConfig(self):
        configQuery = ConfigFile.query(
                ancestor=ndb.Key('ConfigFile', 'config')).order(-ConfigFile.date)
        configs = configQuery.fetch(1)
        if len(configs) == 0:
            return None
        for conf in configs:
            return cgi.escape(conf.content)
    
application = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)
